
#include "stm32h7xx_hal.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

/***
 * 接线：
 * PA2  -    LCD_RES
 * PA4  -    LCD_CS
 * PA5  -    LCD_SCL
 * PA5  -    LCD_D0
 * 3.3v -    LCD_BL
 *
 */

#define OFFSET_X 0x01
#define OFFSET_Y 0x66

#define BUF_LEN  0x100
#define sleep_ms HAL_Delay

#define RST_Pin       GPIO_PIN_5
#define RST_GPIO_Port GPIOC

#define CS_Pin       GPIO_PIN_12
#define CS_GPIO_Port GPIOB


#define CS_0() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)
#define CS_1() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET)

#define RES_0() HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_RESET)
#define RES_1() HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_SET)



static SPI_HandleTypeDef hspi6;    // SPI_HandleTypeDef 结构体变量

static SPI_HandleTypeDef hspi2;

/******************************************************************************************* */
// SPI 初始化

/*************************************************************************************************
 *	函 数 名:	HAL_SPI_MspInit
 *	入口参数:	hspi - SPI_HandleTypeDef定义的变量，即表示定义的 SPI 句柄
 *	返 回 值:	无
 *	函数功能:	初始化 SPI6 引脚
 *	说    明:	无
 *************************************************************************************************/

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
    GPIO_InitTypeDef         GPIO_InitStruct     = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    if(hspi->Instance == SPI2)
    {
        /* USER CODE BEGIN SPI2_MspInit 0 */

        /* USER CODE END SPI2_MspInit 0 */

        /** Initializes the peripherals clock
         */
        PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
        PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
        if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
        {
            // Error_Handler();
        }

        /* Peripheral clock enable */
        __HAL_RCC_SPI2_CLK_ENABLE();

        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        /**SPI2 GPIO Configuration
        PC2_C     ------> SPI2_MISO
        PC3_C     ------> SPI2_MOSI
        PB13     ------> SPI2_SCK
        */
        GPIO_InitStruct.Pin       = GPIO_PIN_2 | GPIO_PIN_3;
        GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull      = GPIO_NOPULL;
        GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        GPIO_InitStruct.Pin       = GPIO_PIN_13;
        GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull      = GPIO_NOPULL;
        GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        /* USER CODE BEGIN SPI2_MspInit 1 */

        /* USER CODE END SPI2_MspInit 1 */
    }
}


static void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* USER CODE BEGIN MX_GPIO_Init_1 */
    /* USER CODE END MX_GPIO_Init_1 */

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOH_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1 | GPIO_PIN_5, GPIO_PIN_RESET);

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);

    /*Configure GPIO pins : PC1 PC5 */
    GPIO_InitStruct.Pin   = GPIO_PIN_1 | GPIO_PIN_5;
    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull  = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /*Configure GPIO pin : PB12 */
    GPIO_InitStruct.Pin   = GPIO_PIN_12;
    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull  = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* USER CODE BEGIN MX_GPIO_Init_2 */
    /* USER CODE END MX_GPIO_Init_2 */
}


/*************************************************************************************************
 *	函 数 名:	MX_SPI6_Init
 *	入口参数:	无
 *	返 回 值:	无
 *	函数功能:	初始化SPI配置
 *	说    明:	使用硬件片选
 *************************************************************************************************/
static void MX_SPI2_Init(void)
{

    /* USER CODE BEGIN SPI2_Init 0 */

    /* USER CODE END SPI2_Init 0 */

    /* USER CODE BEGIN SPI2_Init 1 */

    /* USER CODE END SPI2_Init 1 */
    /* SPI2 parameter configuration*/
    hspi2.Instance                        = SPI2;
    hspi2.Init.Mode                       = SPI_MODE_MASTER;
    hspi2.Init.Direction                  = SPI_DIRECTION_2LINES;
    hspi2.Init.DataSize                   = SPI_DATASIZE_8BIT;
    hspi2.Init.CLKPolarity                = SPI_POLARITY_LOW;
    hspi2.Init.CLKPhase                   = SPI_PHASE_1EDGE;
    hspi2.Init.NSS                        = SPI_NSS_SOFT;
    hspi2.Init.BaudRatePrescaler          = SPI_BAUDRATEPRESCALER_8;
    hspi2.Init.FirstBit                   = SPI_FIRSTBIT_MSB;
    hspi2.Init.TIMode                     = SPI_TIMODE_DISABLE;
    hspi2.Init.CRCCalculation             = SPI_CRCCALCULATION_DISABLE;
    hspi2.Init.CRCPolynomial              = 0x0;
    hspi2.Init.NSSPMode                   = SPI_NSS_PULSE_DISABLE;
    hspi2.Init.NSSPolarity                = SPI_NSS_POLARITY_LOW;
    hspi2.Init.FifoThreshold              = SPI_FIFO_THRESHOLD_01DATA;
    hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
    hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
    hspi2.Init.MasterSSIdleness           = SPI_MASTER_SS_IDLENESS_00CYCLE;
    hspi2.Init.MasterInterDataIdleness    = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
    hspi2.Init.MasterReceiverAutoSusp     = SPI_MASTER_RX_AUTOSUSP_DISABLE;
    hspi2.Init.MasterKeepIOState          = SPI_MASTER_KEEP_IO_STATE_DISABLE;
    hspi2.Init.IOSwap                     = SPI_IO_SWAP_DISABLE;
    if(HAL_SPI_Init(&hspi2) != HAL_OK)
    {
        // Error_Handler();
    }
    /* USER CODE BEGIN SPI2_Init 2 */

    /* USER CODE END SPI2_Init 2 */
}


void MX_SPI6_Init(void)
{
    hspi6.Instance         = SPI6;                    //	使用SPI6
    hspi6.Init.Mode        = SPI_MODE_MASTER;         //	主机模式
    hspi6.Init.Direction   = SPI_DIRECTION_2LINES;    //	双线全双工
    hspi6.Init.DataSize    = SPI_DATASIZE_8BIT;       //	8位数据宽度
    hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;        //	CLK空闲时保持低电平
    hspi6.Init.CLKPhase    = SPI_PHASE_1EDGE;         //	数据在CLK第一个边沿有效
    hspi6.Init.NSS         = SPI_NSS_HARD_OUTPUT;     //	使用硬件片选

    // 这里将 pll2_q_ck 设置为 100M 作为 SPI6 的内核时钟，然后再经过2分频得到 50M 的SCK驱动时钟
    hspi6.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

    hspi6.Init.FirstBit                   = SPI_FIRSTBIT_MSB;                           //	高位在先
    hspi6.Init.TIMode                     = SPI_TIMODE_DISABLE;                         //	禁止TI模式
    hspi6.Init.CRCCalculation             = SPI_CRCCALCULATION_DISABLE;                 //	禁止CRC
    hspi6.Init.CRCPolynomial              = 0x0;                                        // CRC校验项，这里用不到
    hspi6.Init.NSSPMode                   = SPI_NSS_PULSE_DISABLE;                      //	不使用片选脉冲模式
    hspi6.Init.NSSPolarity                = SPI_NSS_POLARITY_LOW;                       //	片选低电平有效
    hspi6.Init.FifoThreshold              = SPI_FIFO_THRESHOLD_02DATA;                  //	FIFO阈值
    hspi6.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;    // 发送端CRC初始化模式，这里用不到
    hspi6.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;    // 接收端CRC初始化模式，这里用不到
    hspi6.Init.MasterSSIdleness           = SPI_MASTER_SS_IDLENESS_00CYCLE;             // 额外延迟周期为0
    hspi6.Init.MasterInterDataIdleness    = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;      // 主机模式下，两个数据帧之间的延迟周期
    hspi6.Init.MasterReceiverAutoSusp     = SPI_MASTER_RX_AUTOSUSP_DISABLE;             // 禁止自动接收管理
    hspi6.Init.MasterKeepIOState          = SPI_MASTER_KEEP_IO_STATE_ENABLE;            //	主机模式下，SPI当前引脚状态
    hspi6.Init.IOSwap                     = SPI_IO_SWAP_DISABLE;                        // 不交换MOSI和MISO

    HAL_SPI_Init(&hspi6);
}



void DEV_SPI_WriteByte(uint8_t value)
{
    HAL_SPI_Transmit(&hspi2, &value, 1, 1000);
}

void DEV_SPI_WriteBytes(uint8_t* p_buf, uint32_t len)
{
    HAL_SPI_Transmit(&hspi2, p_buf, len, 1000);
}

typedef struct
{
    uint8_t        cmd;            // Command byte.
    const uint8_t* param;          // Pointer to parameters.
    uint8_t        param_bytes;    // Bytes of parameters.
    uint16_t       delay_ms;       // Delay in milliseconds after this command.
} lcd_init_cmd_t;

static const lcd_init_cmd_t vendor_specific_init_default[] = {
    {0xF0, (uint8_t[]){0x08},                                                                               1,  0  },
    {0xF2, (uint8_t[]){0x08},                                                                               1,  0  },
    {0x9B, (uint8_t[]){0x51},                                                                               1,  0  },
    {0x86, (uint8_t[]){0x53},                                                                               1,  0  },
    {0xF2, (uint8_t[]){0x80},                                                                               1,  0  },
    {0xF0, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xF0, (uint8_t[]){0x01},                                                                               1,  0  },
    {0xF1, (uint8_t[]){0x01},                                                                               1,  0  },
    {0xB0, (uint8_t[]){0x5E},                                                                               1,  0  },
    {0xB1, (uint8_t[]){0x3D},                                                                               1,  0  },
    {0xB2, (uint8_t[]){0x30},                                                                               1,  0  },
    {0xB4, (uint8_t[]){0x27},                                                                               1,  0  },
    {0xB5, (uint8_t[]){0x34},                                                                               1,  0  },
    {0xB6, (uint8_t[]){0xA5},                                                                               1,  0  },
    {0xB7, (uint8_t[]){0x20},                                                                               1,  0  },
    {0xBA, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xBB, (uint8_t[]){0x08},                                                                               1,  0  },
    {0xBC, (uint8_t[]){0x08},                                                                               1,  0  },
    {0xBD, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xC0, (uint8_t[]){0x80},                                                                               1,  0  },
    {0xC1, (uint8_t[]){0x0B},                                                                               1,  0  },
    {0xC2, (uint8_t[]){0x34},                                                                               1,  0  },
    {0xC3, (uint8_t[]){0x80},                                                                               1,  0  },
    {0xC4, (uint8_t[]){0x0B},                                                                               1,  0  },
    {0xC5, (uint8_t[]){0x34},                                                                               1,  0  },
    {0xC6, (uint8_t[]){0xA9},                                                                               1,  0  },
    {0xC7, (uint8_t[]){0x41},                                                                               1,  0  },
    {0xC8, (uint8_t[]){0x51},                                                                               1,  0  },
    {0xC9, (uint8_t[]){0xA9},                                                                               1,  0  },
    {0xCA, (uint8_t[]){0x41},                                                                               1,  0  },
    {0xCB, (uint8_t[]){0x51},                                                                               1,  0  },
    {0xD0, (uint8_t[]){0xD1},                                                                               1,  0  },
    {0xD1, (uint8_t[]){0x40},                                                                               1,  0  },
    {0xD2, (uint8_t[]){0x83},                                                                               1,  0  },
    {0xF5, (uint8_t[]){0x00, 0xA5},                                                                         2,  0  },
    {0xDD, (uint8_t[]){0x33},                                                                               1,  0  },
    {0xDE, (uint8_t[]){0x33},                                                                               1,  0  },
    {0xF1, (uint8_t[]){0x10},                                                                               1,  0  },
    {0xF0, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xF0, (uint8_t[]){0x02},                                                                               1,  0  },
    {0xE0, (uint8_t[]){0xF0, 0x0A, 0x10, 0x0A, 0x09, 0x15, 0x37, 0x33, 0x4F, 0x38, 0x14, 0x14, 0x32, 0x36}, 14, 0  },
    {0xE1, (uint8_t[]){0xF0, 0x09, 0x0F, 0x0A, 0x09, 0x25, 0x37, 0x33, 0x4F, 0x37, 0x13, 0x14, 0x31, 0x35}, 14, 0  },
#if 1
    {0xF0, (uint8_t[]){0x10},                                                                               1,  0  },
    {0xF3, (uint8_t[]){0x10},                                                                               1,  0  },
    {0xE0, (uint8_t[]){0x0C},                                                                               1,  0  },
    {0xE1, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xE2, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xE3, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xE4, (uint8_t[]){0xE0},                                                                               1,  0  },
    {0xE5, (uint8_t[]){0x06},                                                                               1,  0  },
    {0xE6, (uint8_t[]){0x21},                                                                               1,  0  },
    {0xE7, (uint8_t[]){0x10},                                                                               1,  0  },
    {0xE8, (uint8_t[]){0x85},                                                                               1,  0  },
    {0xE9, (uint8_t[]){0x83},                                                                               1,  0  },
    {0xEA, (uint8_t[]){0x16},                                                                               1,  0  },
    {0xEB, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xEC, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xED, (uint8_t[]){0x14},                                                                               1,  0  },
    {0xEE, (uint8_t[]){0xFF},                                                                               1,  0  },
    {0xEF, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xF8, (uint8_t[]){0xFF},                                                                               1,  0  },
    {0xF9, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xFA, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xFB, (uint8_t[]){0x30},                                                                               1,  0  },
    {0xFC, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xFD, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xFE, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xFF, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x60, (uint8_t[]){0x43},                                                                               1,  0  },
    {0x61, (uint8_t[]){0x1A},                                                                               1,  0  },
    {0x62, (uint8_t[]){0x40},                                                                               1,  0  },
    {0x63, (uint8_t[]){0x40},                                                                               1,  0  },
    {0x64, (uint8_t[]){0x02},                                                                               1,  0  },
    {0x65, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x66, (uint8_t[]){0x40},                                                                               1,  0  },
    {0x67, (uint8_t[]){0x03},                                                                               1,  0  },
    {0x68, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x69, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x6A, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x6B, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x70, (uint8_t[]){0x43},                                                                               1,  0  },
    {0x71, (uint8_t[]){0x1A},                                                                               1,  0  },
    {0x72, (uint8_t[]){0x40},                                                                               1,  0  },
    {0x73, (uint8_t[]){0x40},                                                                               1,  0  },
    {0x74, (uint8_t[]){0x02},                                                                               1,  0  },
    {0x75, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x76, (uint8_t[]){0x40},                                                                               1,  0  },
    {0x77, (uint8_t[]){0x03},                                                                               1,  0  },
    {0x78, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x79, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x7A, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x7B, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x80, (uint8_t[]){0x48},                                                                               1,  0  },
    {0x81, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x82, (uint8_t[]){0x07},                                                                               1,  0  },
    {0x83, (uint8_t[]){0x03},                                                                               1,  0  },
    {0x84, (uint8_t[]){0x17},                                                                               1,  0  },
    {0x85, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x86, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x87, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x88, (uint8_t[]){0x48},                                                                               1,  0  },
    {0x89, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x8A, (uint8_t[]){0x09},                                                                               1,  0  },
    {0x8B, (uint8_t[]){0x03},                                                                               1,  0  },
    {0x8C, (uint8_t[]){0x19},                                                                               1,  0  },
    {0x8D, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x8E, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x8F, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x90, (uint8_t[]){0x48},                                                                               1,  0  },
    {0x91, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x92, (uint8_t[]){0x0B},                                                                               1,  0  },
    {0x93, (uint8_t[]){0x03},                                                                               1,  0  },
    {0x94, (uint8_t[]){0x13},                                                                               1,  0  },
    {0x95, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x96, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x97, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x98, (uint8_t[]){0x48},                                                                               1,  0  },
    {0x99, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x9A, (uint8_t[]){0x0D},                                                                               1,  0  },
    {0x9B, (uint8_t[]){0x03},                                                                               1,  0  },
    {0x9C, (uint8_t[]){0x15},                                                                               1,  0  },
    {0x9D, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x9E, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x9F, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xA0, (uint8_t[]){0x48},                                                                               1,  0  },
    {0xA1, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xA2, (uint8_t[]){0x06},                                                                               1,  0  },
    {0xA3, (uint8_t[]){0x03},                                                                               1,  0  },
    {0xA4, (uint8_t[]){0x16},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xA6, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xA7, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xA8, (uint8_t[]){0x48},                                                                               1,  0  },
    {0xA9, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xAA, (uint8_t[]){0x08},                                                                               1,  0  },
    {0xAB, (uint8_t[]){0x03},                                                                               1,  0  },
    {0xAC, (uint8_t[]){0x18},                                                                               1,  0  },
    {0xAD, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xAE, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xAF, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xB0, (uint8_t[]){0x48},                                                                               1,  0  },
    {0xB1, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xB2, (uint8_t[]){0x0A},                                                                               1,  0  },
    {0xB3, (uint8_t[]){0x03},                                                                               1,  0  },
    {0xB4, (uint8_t[]){0x12},                                                                               1,  0  },
    {0xB5, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xB6, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xB7, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xB8, (uint8_t[]){0x48},                                                                               1,  0  },
    {0xB9, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xBA, (uint8_t[]){0x0C},                                                                               1,  0  },
    {0xBB, (uint8_t[]){0x03},                                                                               1,  0  },
    {0xBC, (uint8_t[]){0x14},                                                                               1,  0  },
    {0xBD, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xBE, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xBF, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xC0, (uint8_t[]){0x45},                                                                               1,  0  },
    {0xC1, (uint8_t[]){0x54},                                                                               1,  0  },
    {0xC2, (uint8_t[]){0x67},                                                                               1,  0  },
    {0xC3, (uint8_t[]){0x76},                                                                               1,  0  },
    {0xC4, (uint8_t[]){0x88},                                                                               1,  0  },
    {0xC5, (uint8_t[]){0xAA},                                                                               1,  0  },
    {0xC6, (uint8_t[]){0x22},                                                                               1,  0  },
    {0xC7, (uint8_t[]){0xBB},                                                                               1,  0  },
    {0xC8, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xC9, (uint8_t[]){0x99},                                                                               1,  0  },
    {0xD0, (uint8_t[]){0x45},                                                                               1,  0  },
    {0xD1, (uint8_t[]){0x54},                                                                               1,  0  },
    {0xD2, (uint8_t[]){0x67},                                                                               1,  0  },
    {0xD3, (uint8_t[]){0x76},                                                                               1,  0  },
    {0xD4, (uint8_t[]){0x88},                                                                               1,  0  },
    {0xD5, (uint8_t[]){0xAA},                                                                               1,  0  },
    {0xD6, (uint8_t[]){0x11},                                                                               1,  0  },
    {0xD7, (uint8_t[]){0xBB},                                                                               1,  0  },
    {0xD8, (uint8_t[]){0x00},                                                                               1,  0  },
    {0xD9, (uint8_t[]){0x99},                                                                               1,  0  },
    {0xF3, (uint8_t[]){0x01},                                                                               1,  0  },
    {0xF0, (uint8_t[]){0x00},                                                                               1,  0  },
#endif
#if 0
    {0xF0, (uint8_t[]){0x01},                                                                               1,  0  },
    {0xF1, (uint8_t[]){0x01},                                                                               1,  0  },
    {0xA0, (uint8_t[]){0x0B},                                                                               1,  0  },
    {0xA3, (uint8_t[]){0x2A},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x2B},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x2C},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x2D},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x2E},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x2F},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x30},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x31},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA3, (uint8_t[]){0x32},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  100},
    {0xA3, (uint8_t[]){0x33},                                                                               1,  0  },
    {0xA5, (uint8_t[]){0xC3},                                                                               1,  10 },
    {0xA0, (uint8_t[]){0x09},                                                                               1,  0  },
    {0xF1, (uint8_t[]){0x10},                                                                               1,  0  },
    {0xF0, (uint8_t[]){0x00},                                                                               1,  0  },
#endif
    {0x4D, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x4E, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x4F, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x4C, (uint8_t[]){0x01},                                                                               1,  10 },
    {0x2A, (uint8_t[]){0x00, 0x00, 0x01, 0x81},                                                             4,  0  },
    {0x2B, (uint8_t[]){0x00, 66, 0x01, 0x81},                                                               4,  0  },
    {0x21, (uint8_t[]){0x00},                                                                               0,  0  },
    {0x35, (uint8_t[]){0x00},                                                                               1,  0  },
    {0x36, (uint8_t[]){0x60},                                                                               1,  0  },
    {0x11, (uint8_t[]){0x00},                                                                               0,  120},
    {0x3A, (uint8_t[]){0x55},                                                                               1,  0  },
    {0x29, (uint8_t[]){0x00},                                                                               0,  50 },
};

static uint16_t g_cl_buf[386];

static void _write_reg(uint8_t cmd, const uint8_t* param, uint32_t len)
{
    CS_0();

    // cmd
    uint8_t cmd_buf[4] = {0x02, 0, cmd, 0};

    DEV_SPI_WriteBytes(cmd_buf, sizeof(cmd_buf));

    if(len != 0)
    {
        DEV_SPI_WriteBytes((uint8_t*)param, len);
        // printf("Write len:%d\n", len);
    }

    CS_1();
}

static void st7789_set_tft_spec(void)
{
    lcd_init_cmd_t* init_cmds      = (lcd_init_cmd_t*)vendor_specific_init_default;
    uint16_t        init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(vendor_specific_init_default[0]);
    for(int i = 0; i < init_cmds_size; i++)
    {
        _write_reg(init_cmds[i].cmd, init_cmds[i].param, init_cmds[i].param_bytes);
        // tx_param(st7789v3, io, init_cmds[i].cmd, init_cmds[i].param, init_cmds[i].param_bytes);
        sleep_ms(init_cmds[i].delay_ms);
    }
}

static void clear_screen(uint8_t r, uint8_t g, uint8_t b)
{
    uint16_t cl = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b >> 3);

    for(uint16_t i = 0; i < 386; i++)
    {
        g_cl_buf[i] = cl;
    }

    _write_reg(0x2c, (const uint8_t*)g_cl_buf, sizeof(g_cl_buf));
    for(size_t i = 0; i < 319; i++)
    {
        _write_reg(0x3c, (const uint8_t*)g_cl_buf, sizeof(g_cl_buf));
        // DEV_SPI_WriteBytes((uint8_t*)g_cl_buf, sizeof(g_cl_buf));
    }
}

static void _reset_lcd(void)
{
    RES_0();
    sleep_ms(100);
    RES_1();
    sleep_ms(100);
}

static void set_region(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
    // x0 += OFFSET_X;
    // x1 += OFFSET_X;
    // y0 += OFFSET_Y;
    // y1 += OFFSET_Y;

    uint8_t reg_2a[4] = {x0 >> 8, x0 & 0xff, x1 >> 8, x1 & 0xff};
    uint8_t reg_2b[4] = {y0 >> 8, y0 & 0xff, y1 >> 8, y1 & 0xff};

    _write_reg(0x2a, reg_2a, 4);
    _write_reg(0x2b, reg_2b, 4);
}


void _spi_init(void)
{
    // DEV_Module_Init();

    // MX_SPI6_Init();
    MX_SPI2_Init();
    MX_GPIO_Init();


    _reset_lcd();
    st7789_set_tft_spec();
}

// 可用接口
static void fill_img(uint8_t* p_buf, uint32_t len)
{
    uint8_t cmd[] = {0x02, 0x00, 0x2c, 0x00};

    // set_region(0, 0, 319, 385);

    uint8_t* p = p_buf;

    _write_reg(0x2c, (const uint8_t*)&p[0], 386 * 2);
    for(size_t i = 0; i < 319; i++)
    {
        _write_reg(0x3c, (const uint8_t*)(&p[386 * 2 * (i + 1)]), 386 * 2);
    }

    // _write_reg(0x2c, (const uint8_t*)p_buf, len);

    // CS_0();
    // DEV_SPI_WriteBytes(cmd, sizeof(cmd));
    // DEV_SPI_WriteBytes(p_buf, len);
    // CS_1();
}

void lcd_77916_test(void)
{
    _spi_init();

    extern const unsigned char hor_girl_bmp[386 * 320 * 2];

    while(1)
    {
        // fill_img((uint8_t*)hor_girl_bmp, sizeof(hor_girl_bmp));
        // sleep_ms(1000);

        clear_screen(0xff, 0, 0);
        sleep_ms(1000);

        clear_screen(0, 0xff, 0);
        sleep_ms(1000);

        clear_screen(0, 0, 0xff);
        sleep_ms(1000);
    }
}

// extern api
void disp_st77916_init(void)
{
    _spi_init();
    // set_region(x1, y1 - 1, x2, y2 - 1);
    clear_screen(255, 0, 0);
}

void disp_st77916_update(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t* p_buf)
{
    uint32_t len = (x2 - x1) * (y2 - y1) * 2;
    // set_region(x1, y1 - 1, x2, y2 - 1);
    fill_img((uint8_t*)p_buf, len);
}


// 设置旋转
/**
 ********************************************************************************************************
 * @brief
 *
 * @param   rotate
 * 0-不旋转
 * 90：顺时针旋转 90 度
 * 180：顺时针旋转 180 度
 * 270：顺时针旋转 270 度
 ********************************************************************************************************
 **/
void disp_st77916_rotate(uint16_t rotate)
{
    if(rotate == 90)
    {
        uint8_t reg_2a[4] = {0x00, 0x00, 0x01, 0x81};
        uint8_t reg_2b[4] = {0x00, 66, 0x01, 0x81};

        _write_reg(0x2a, reg_2a, 4);
        _write_reg(0x2b, reg_2b, 4);

        uint8_t reg = 0x60;
        _write_reg(0x36, &reg, 1);
    }
    else if(rotate == 180)
    {
        uint8_t reg_2a[4] = {0x00, 0x00, 0x01, 0x3F};
        uint8_t reg_2b[4] = {0x00, 0x00, 0x01, 0x81};

        _write_reg(0x2a, reg_2a, 4);
        _write_reg(0x2b, reg_2b, 4);

        uint8_t reg = 0xC0;
        _write_reg(0x36, &reg, 1);
    }
    else if(rotate == 270)
    {
        uint8_t reg_2a[4] = {0x00, 0x00, 0x01, 0x81};
        uint8_t reg_2b[4] = {0x00, 66, 0x01, 0x81};

        _write_reg(0x2a, reg_2a, 4);
        _write_reg(0x2b, reg_2b, 4);

        uint8_t reg = 0xE0;
        _write_reg(0x36, &reg, 1);
    }
    else
    {
        uint8_t reg_2a[4] = {0x00, 0x00, 0x01, 0x3F};
        uint8_t reg_2b[4] = {0x00, 0x00, 0x01, 0x81};

        _write_reg(0x2a, reg_2a, 4);
        _write_reg(0x2b, reg_2b, 4);

        uint8_t reg = 0x00;
        _write_reg(0x36, &reg, 1);
    }
}
